#include "thumbnailbarwidget.h"
#include "dicomimagelabel.h"
#include "imageloadthread.h"
#include "seriesinstance.h"
#include "imageinstance.h"

#include "dcmtk/dcmdata/dcuid.h"

#include <QDragEnterEvent>
#include <QDragMoveEvent>
#include <QDropEvent>
#include <QKeyEvent>

#include <QMessageBox>

ThumbnailBarWidget::ThumbnailBarWidget(QWidget *parent) :
    currentImageLabel(0),
    QWidget(parent)
{
    setFocusPolicy(Qt::StrongFocus);
    layout = new QBoxLayout(QBoxLayout::TopToBottom, this);
    layout->setContentsMargins(6, 6, 6, 6);
    layout->addStretch();
    layout->setAlignment(Qt::AlignCenter);
}

void ThumbnailBarWidget::setCurrentImageLabel(const SeriesInstance *series)
{
    if (currentImageLabel && currentImageLabel->getSeriesInstance() == series)
        return;

    bool found = false;
    foreach (DicomImageLabel *label, imageLabelList) {
        if (series == label->getSeriesInstance()) {
            if (currentImageLabel) currentImageLabel->setHighlight(false);
            currentImageLabel = label;
            currentImageLabel->setHighlight(true);
            found = true;
            break;
        }
    }
    if ((!found) && currentImageLabel) {
        currentImageLabel->setHighlight(false);
        currentImageLabel = 0;
    }
}

void ThumbnailBarWidget::updateLabelImage(const SeriesInstance *series)
{
    if (currentImageLabel && currentImageLabel->getSeriesInstance()==series) {
        currentImageLabel->updateThumbnailImage();
        return;
    }

    foreach (DicomImageLabel *label, imageLabelList) {
        if (label->getSeriesInstance() == series) {
            label->updateThumbnailImage();
            break;
        }
    }
}

void ThumbnailBarWidget::appendFileFormat(DcmFileFormat *dcmff)
{
    if (dcmff) onImageReady(new ImageInstance(dcmff));
}

void ThumbnailBarWidget::appendImageFiles(const QStringList &files, bool clearOld)
{
    QStringList unloadedFiles;

    if (clearOld) {
        unloadedFiles = files;
        clear();
    } else {
        foreach (const QString &file, files) {
            bool found = false;
            foreach (DicomImageLabel *label, imageLabelList) {
                if (label->hasImage(file)) {
                    found = true;
                    break;
                }
            }
            if (!found) unloadedFiles << file;
        }
    }

    ImageLoadThread *thread = new ImageLoadThread;
    connect(thread, SIGNAL(resultReady(ImageInstance*)), this, SLOT(onImageReady(ImageInstance*)));
    connect(thread, SIGNAL(finished()), this, SLOT(onLoadFinished()));
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
    thread->setImageFiles(unloadedFiles);
    thread->start();
}

void ThumbnailBarWidget::onImageReady(ImageInstance *image)
{
    bool inserted = false;
    foreach (DicomImageLabel *label, imageLabelList) {
        if (label->insertImage(image)) {
            inserted = true;
            break;
        }
    }
    if ((!inserted) && image) {
        DicomImageLabel *imageLabel = new DicomImageLabel(new SeriesInstance(image->seriesUid()));
        imageLabel->insertImage(image);
        connect(imageLabel, SIGNAL(imageClicked(DicomImageLabel*)),
                this, SLOT(onImageClicked(DicomImageLabel*)));
        connect(imageLabel, SIGNAL(imageDoubleClicked(DicomImageLabel*)),
                this, SLOT(onImageDoubleClicked(DicomImageLabel*)));
        layout->insertWidget(imageLabelList.size(), imageLabel);
        imageLabelList.append(imageLabel);
        if (!currentImageLabel) setCurrentImageLabel(imageLabel->getSeriesInstance());
    }
}

void ThumbnailBarWidget::onImageClicked(DicomImageLabel *imageLabel)
{
    if (currentImageLabel != imageLabel) {
        if (currentImageLabel) currentImageLabel->setHighlight(false);
        currentImageLabel = imageLabel;
        if (currentImageLabel) {
            currentImageLabel->setHighlight(true);
            emit currentChanged(currentImageLabel);
        }
    }
}

void ThumbnailBarWidget::onImageDoubleClicked(DicomImageLabel *imageLabel)
{
    if (currentImageLabel) currentImageLabel->setHighlight(false);
    currentImageLabel = imageLabel;
    if (currentImageLabel) {
        currentImageLabel->setHighlight(true);
        emit imageDoubleClicked(currentImageLabel);
    }
}

void ThumbnailBarWidget::onLoadFinished()
{
    if (currentImageLabel)
        emit seriesInserted(currentImageLabel->getSeriesInstance());
}

QList<SeriesInstance *> ThumbnailBarWidget::getSeriesList() const
{
    QList<SeriesInstance*> seriesList;
    foreach (DicomImageLabel *label, imageLabelList) {
        seriesList << label->getSeriesInstance();
    }
    return seriesList;
}

QSize ThumbnailBarWidget::sizeHint() const
{
    QMargins margin = layout->contentsMargins();
    int width = DicomImageLabel::getImageLabelSize();
    int height = DicomImageLabel::getImageLabelSize()*imageLabelList.size();
    if (imageLabelList.size() > 1)
        height += (imageLabelList.size()-1)*layout->spacing();

    switch (layout->direction()) {
    case QBoxLayout::TopToBottom:
    case QBoxLayout::BottomToTop:
        return QSize(width + margin.left() + margin.right(),
                     height + margin.top() + margin.bottom());
        break;
    case QBoxLayout::LeftToRight:
    case QBoxLayout::RightToLeft:
        return QSize(width + margin.top() + margin.bottom(),
                     height + margin.left() + margin.right());
        break;
    default:
        return QSize();
    }
}

void ThumbnailBarWidget::clear()
{
    qDeleteAll(imageLabelList);
    imageLabelList.clear();
    currentImageLabel = 0;
}

void ThumbnailBarWidget::keyPressEvent(QKeyEvent *e)
{
    switch (e->key()) {
    case Qt::Key_Return:
        if (currentImageLabel) emit imageDoubleClicked(currentImageLabel);
        break;
    case Qt::Key_Home:
        if (currentImageLabel && (currentImageLabel != imageLabelList.first())) {
            currentImageLabel->setHighlight(false);
            currentImageLabel = imageLabelList.first();
            currentImageLabel->setHighlight(true);
            emit currentChanged(currentImageLabel);
        } else if ((!currentImageLabel) && imageLabelList.size()) {
            currentImageLabel = imageLabelList.first();
            currentImageLabel->setHighlight(true);
            emit currentChanged(currentImageLabel);
        }
        break;
    case Qt::Key_PageDown:
    case Qt::Key_Down:
    case Qt::Key_Right:
        if (currentImageLabel && (imageLabelList.size()>1)) {
            currentImageLabel->setHighlight(false);
            if (currentImageLabel == imageLabelList.last()) currentImageLabel = imageLabelList.first();
            else currentImageLabel = imageLabelList.at(imageLabelList.indexOf(currentImageLabel)+1);
            currentImageLabel->setHighlight(true);
            emit currentChanged(currentImageLabel);
        } else if (imageLabelList.size()) {
            currentImageLabel = imageLabelList.first();
            currentImageLabel->setHighlight(true);
            emit currentChanged(currentImageLabel);
        }
        break;
    case Qt::Key_End:
        if (currentImageLabel && (currentImageLabel != imageLabelList.last())) {
            currentImageLabel->setHighlight(false);
            currentImageLabel = imageLabelList.last();
            currentImageLabel->setHighlight(true);
            emit currentChanged(currentImageLabel);
        } else if ((!currentImageLabel) && imageLabelList.size()) {
            currentImageLabel = imageLabelList.last();
            currentImageLabel->setHighlight(true);
            emit currentChanged(currentImageLabel);
        }
        break;
    case Qt::Key_PageUp:
    case Qt::Key_Up:
    case Qt::Key_Left:
        if (currentImageLabel && (imageLabelList.size()>1)) {
            currentImageLabel->setHighlight(false);
            if (currentImageLabel == imageLabelList.first()) currentImageLabel = imageLabelList.last();
            else currentImageLabel = imageLabelList.at(imageLabelList.indexOf(currentImageLabel)-1);
            currentImageLabel->setHighlight(true);
            emit currentChanged(currentImageLabel);
        } else if (imageLabelList.size()) {
            currentImageLabel = imageLabelList.last();
            currentImageLabel->setHighlight(true);
            emit currentChanged(currentImageLabel);
        }
        break;
    default:
        QWidget::keyPressEvent(e);
    }
}
